package com.gonsin.gview.common.services.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gonsin.base.GPageRequest;
import com.gonsin.base.GPageResult;
import com.gonsin.base.exceptions.MyException;
import com.gonsin.gview.annotations.data.GDataSource;
import com.gonsin.gview.common.auth.BaseResultCodes;
import com.gonsin.gview.common.auth.UserResultCode;
import com.gonsin.gview.common.bean.EdificeBean;
import com.gonsin.gview.common.bean.UserAndEdificeBean;
import com.gonsin.gview.common.bean.UserBean;
import com.gonsin.gview.common.config.GViewResourceProperties;
import com.gonsin.gview.common.mapper.EdificeMapper;
import com.gonsin.gview.common.mapper.UserAndEdificeMapper;
import com.gonsin.gview.common.mapper.UserMapper;
import com.gonsin.gview.common.po.*;
import com.gonsin.gview.common.services.IMenusService;
import com.gonsin.gview.common.services.IUserService;
import com.gonsin.gview.common.utils.KeyOnlyUtils;
import com.gonsin.gview.common.utils.PageableUtils;
import com.gonsin.gview.logic.config.GViewMenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.annotation.Primary;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

@Service("gviewUserService")
public class UserServiceImpl extends ServiceImpl<UserMapper, UserBean> implements IUserService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private IMenusService menusService;
    @Autowired
    private EdificeMapper edificeMapper;
    @Autowired
    private UserAndEdificeMapper userAndEdificeMapper;

    @Autowired(required = false)
    private GViewResourceProperties resourceProperties;

    @Autowired(required = false)
    private GViewMenuService gViewMenuService;

    @Transactional
    public void resetUserMessageKey(String userMessageKey) {
        UpdateWrapper<UserBean> wrapper = new UpdateWrapper<>();
        wrapper.eq("user_message_key", userMessageKey);
        wrapper.set("user_message_key", null);
        this.update(wrapper);
    }

    @Transactional
    public void bindUserMessageKey(String userMessageKey, String userKey) {
        UpdateWrapper<UserBean> wrapper = new UpdateWrapper<>();
        wrapper.eq("user_key", userKey);
        wrapper.set("user_message_key", userMessageKey);
        this.update(wrapper);
    }

    @GDataSource("getAllAvailableUserList")
    public List<Map<String, Object>> getAllAvailableUserList() {
        return userMapper.getAllAvailableUserList();
    }

    @Override
    public List<UserBean> findAllRendAdmin(String edificeKey) {
        return userMapper.findAllRendAdmin(edificeKey);
    }

    @Override
    public UserBo login(String username, String password) {

        UserBo user = userMapper.findByUsername(username);
        if (user == null) {
            throw new MyException(BaseResultCodes.NOT_FOUND.getValue(), "找不到该用户");
        }

        // 密码错误
        String pwd = user.getPassword();
        if (!StringUtils.equals(password, pwd)) {
            throw new MyException(BaseResultCodes.PASSWORD_WRONG);
        }
        user.setPassword(null);

        List<String> edificeKeys = userAndEdificeMapper.findByUserKey(user.getUserKey());
        user.setEdificeKeys(edificeKeys);
//        if(gViewMenuService != null){
//            gViewMenuService.get
//        }
//        user.setPermissions();

        return user;
    }

    @Override
    public UserBo loginByLoginId(String loginId) {
        UserBo user = userMapper.findByLoginId(loginId);
        if (user == null) {
            throw new MyException(BaseResultCodes.NOT_FOUND.getValue(), "找不到该用户");
        }
        return user;
    }

    @Override
    @GDataSource("getUser")
    public UserBean getUser(String userKey) {
        return userMapper.getUser(userKey);
    }

    @Override
    public UserBean getUserByName(String userName) {
        return userMapper.getUserByName(userName);
    }

    @Override
    public GPageResult<UserBean> searchUser(String edificeKey, UserSearchPo searchPo, GPageRequest pageRequest) {
        if (StringUtils.isEmpty(pageRequest.getSort())) {
            pageRequest.setSort("-create_time");
        }
        List<UserBean> list = userMapper.searchUser(edificeKey, searchPo, PageableUtils.toPageableMyBatis(pageRequest));
        int count = userMapper.countUser(edificeKey, searchPo);
        return GPageResult.result(list, count, pageRequest);
    }

    @Override
    public UserBean updateUser(String userKey, UserPo user) {
        UserBean u = userMapper.selectById(userKey);
        if (u == null) {
            throw new MyException(UserResultCode.USER_NOT_FOUND);
        }
        BeanUtil.copyProperties(user, u, CopyOptions.create().setIgnoreNullValue(true).setIgnoreCase(true).setIgnoreError(true));
        userMapper.updateById(u);
        return u;
    }

    @Override
    @Transactional
    public UserBean addUser(String edificeKey, UserPo user) {

        UserBean u = userMapper.findByUsername(user.getUsername());
        if(u != null){
            String existEdificeKey = userAndEdificeMapper.findRelation(u.getUserKey(), edificeKey);
            if(existEdificeKey != null){
                throw new MyException(UserResultCode.USER_EXIST);
            }
        }

        if(StringUtils.isNotEmpty(user.getPhone())){
            u = userMapper.findByPhone(user.getPhone());
            if(u != null){
                String existEdificeKey = userAndEdificeMapper.findRelation(u.getUserKey(), edificeKey);
                if(existEdificeKey != null){
                    throw new MyException(UserResultCode.USER_EXIST);
                }
            }
        }

        u = new UserBean();
        if(StringUtils.isEmpty(user.getPhone())){
            user.setPhone(null);
        }
        BeanUtil.copyProperties(user, u, CopyOptions.create().setIgnoreNullValue(true).setIgnoreCase(true).setIgnoreError(true));
        u.setUserKey(KeyOnlyUtils.general("user"));
        userMapper.insert(u);

        // 插入关系
        UserAndEdificeBean userAndEdifice = new UserAndEdificeBean();
        userAndEdifice.setEdificeKey(edificeKey);
        userAndEdifice.setUserKey(u.getUserKey());
        userAndEdificeMapper.insert(userAndEdifice);

        return u;
    }

    @Override
    public void deleteUser(String userKey) {
        userMapper.deleteById(userKey);
    }

    @Override
    public void batchDeleteUser(String edificeKey, UserSearchPo searchPo) {
        List<UserBean> list = userMapper.searchUser(edificeKey, searchPo, PageableUtils.toPageableMyBatis(GPageRequest.all()));
        for (UserBean u : list) {
            deleteUser(u.getUserKey());
        }
    }


    @EventListener(value = ApplicationStartedEvent.class)
    public void initAdmin(){
        if(resourceProperties == null){
            return;
        }

        if(StringUtils.isAnyEmpty(resourceProperties.getDefaultUsername(), resourceProperties.getDefaultPassword())){
            return;
        }

        String edificeKey = "gview";
        long count = userMapper.countUser(edificeKey, UserSearchPo.builder().userType("admin").build());
        if(count <= 0){
            EdificeBean e = new EdificeBean();
            e.setName("默认");
            e.setEdificeKey(edificeKey);
            edificeMapper.insert(e);

            UserBean ad = new UserBean();
            ad.setPassword(resourceProperties.getDefaultPassword());
            ad.setLanguage("zh-cn");
            ad.setRealName("管理员");
            ad.setUsername(resourceProperties.getDefaultUsername());
            ad.setUserType("admin");
            ad.setUserKey(KeyOnlyUtils.general("user"));
            ad.setRootUserKey(ad.getUserKey());
            userMapper.insert(ad);


            UserAndEdificeBean ue = new UserAndEdificeBean();
            ue.setUserKey(ad.getUserKey());
            ue.setEdificeKey(edificeKey);
            userAndEdificeMapper.insert(ue);
        }
    }
}
